package com.kordar.admin.modular.sys.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.kordar.admin.enums.EnumUtils;
import com.kordar.admin.kernel.util.HelperUtil;
import com.kordar.admin.kernel.wrapper.BatchDeleteWrapperEntity;
import com.kordar.admin.kernel.wrapper.QueryWrapperEntity;
import com.kordar.admin.kernel.wrapper.UpdateWrapperEntity;
import com.kordar.admin.modular.sys.entity.AdminEntity;
import com.kordar.admin.modular.sys.entity.ResetPasswordForm;
import com.kordar.admin.modular.sys.enums.AdminStatus;
import com.kordar.admin.modular.sys.enums.AdminType;
import com.kordar.admin.modular.sys.service.AdminService;
import com.kordar.auth.Admin;
import com.kordar.auth.AuthException;
import com.kordar.datalist.DatalistService;
import com.kordar.datalist.ExcelDatalistService;
import com.kordar.datalist.ResultEntity;
import com.kordar.rbac.AuthManager;
import com.kordar.rbac.Item;
import com.kordar.rbac.ItemEnum;
import lombok.Data;
import org.apache.catalina.Role;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@Controller
@RequestMapping("sys")
public class AdminController {

    final
    AdminService adminService;

    @Resource(type = DatalistService.class)
    DatalistService datalistService;

    @Resource(type = ExcelDatalistService.class)
    ExcelDatalistService excelDatalistService;

    final
    AuthManager authManager;

    public AdminController(AdminService adminService, AuthManager authManager) {
        this.adminService = adminService;
        this.authManager = authManager;
    }

    @GetMapping("admin/index")
    public String index() {
        return "pages/modular/system/admin/index";
    }

    @ModelAttribute("statusLabels")
    public Map<Integer, String> statusLabels() {
        return EnumUtils.EnumToMapInt(AdminStatus.class);
    }

    @ModelAttribute("typeLabels")
    public Map<Integer, String> typeLabels() {
        return EnumUtils.EnumToMapInt(AdminType.class);
    }


    @RequestMapping("admin/list")
    @ResponseBody
    public ResultEntity<Object> menuList(@RequestBody QueryWrapperEntity<AdminEntity> entity) {
        IPage<AdminEntity> iPage = adminService.iPage(entity);
        return new ResultEntity<>(datalistService.render(iPage.getRecords(), AdminEntity.class), iPage.getTotal());
    }

    @RequestMapping("admin/excel-list")
    @ResponseBody
    public ResultEntity<Object> excel(@RequestBody QueryWrapperEntity<AdminEntity> entity) {
        IPage<AdminEntity> iPage = adminService.excelData(entity, 10000);
        return new ResultEntity<>(excelDatalistService.render(iPage.getRecords(), AdminEntity.class));
    }

    @GetMapping("admin/form")
    public String form(Model model, @RequestParam(required = false, defaultValue = "0") Long id) {

        if (id.equals(0L)) {
            model.addAttribute("header", "新建管理员");
            model.addAttribute("admin", new AdminEntity());
        } else {
            model.addAttribute("header", "修改管理员");
            // System.out.println(adminService.findOne(id));
            model.addAttribute("admin", adminService.findOne(id));
        }

        return "pages/modular/system/admin/form";
    }

    @PostMapping("admin/save")
    @ResponseBody
    public ResultEntity<Object> save(@Validated AdminEntity adminEntity) {
        if (adminEntity.getId() == 0) {
            adminEntity.setId(null);
            adminEntity.generatePassword("123456");
            adminEntity.generateAvatar();
            adminService.save(adminEntity);
        } else {
            adminService.updateById(adminEntity);
        }

        return new ResultEntity<>();
    }

    @RequestMapping("admin/edit")
    @ResponseBody
    public ResultEntity<Object> edit(@RequestBody UpdateWrapperEntity<AdminEntity> entity) {
        UpdateWrapper<AdminEntity> query = entity.where(AdminEntity.class).data().getQuery();
        adminService.update(query);
        return new ResultEntity<>();
    }

    @PostMapping("admin/delete")
    @ResponseBody
    public ResultEntity<Object> del(ServletRequest request, long id) throws AuthException {
        Admin admin = (Admin) request.getAttribute("admin");
        if (admin.getId() == id) {
            throw new AuthException("禁止删除");
        }
        adminService.removeById(id);
        authManager.revokeAll(id);
        return new ResultEntity<>();
    }

    @RequestMapping("admin/batch-delete")
    @ResponseBody
    public ResultEntity<Object> del(ServletRequest request, @RequestBody BatchDeleteWrapperEntity<Long> entity) {
        Set<Long> ids = entity.getIds();
        ids.forEach(authManager::revokeAll);
        adminService.removeByIds(ids);
        return new ResultEntity<>();
    }

    @RequestMapping(value = "admin/assign", method = {RequestMethod.GET})
    public String adminAssign(Model model, Long userId) {
        model.addAttribute("userId", userId);
        model.addAttribute("childrenRole", authManager.getRolesByUser(userId).stream().map(Item::getName).collect(Collectors.toSet()));
        model.addAttribute("childrenPermission", authManager.getPermissionsByUser(userId).stream().map(Item::getName).collect(Collectors.toSet()));
        model.addAttribute("pTree", JSON.toJSONString(HelperUtil.layuiPermissionTree(authManager.getPermissions())));
        model.addAttribute("rTree", JSON.toJSONString(HelperUtil.layuiRoleTree(authManager.getRoles(), null)));
        return "pages/modular/system/admin/assign";
    }

    @Data
    private static class AssignBody {
        private Long userId;
        private Set<String> ids;
        private Integer type = ItemEnum.TYPE_PERMISSION.getCode();
    }

    @RequestMapping(value = "admin/assign/add", method = {RequestMethod.POST})
    @ResponseBody
    public ResultEntity<Object> adminAssignAdd(@RequestBody AssignBody assignBody) {
        for (String name : assignBody.getIds()) {
            Item item = assignBody.getType().equals(ItemEnum.TYPE_PERMISSION.getCode()) ? authManager.getPermission(name) : authManager.getRole(name);
            if (item != null) {
                try {
                    authManager.assign(item, assignBody.getUserId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return new ResultEntity<>();
    }

    @RequestMapping(value = "admin/assign/del", method = {RequestMethod.POST})
    @ResponseBody
    public ResultEntity<Object> roleAssignDel(@RequestBody AssignBody assignBody) {
        for (String name : assignBody.getIds()) {
            Item item = assignBody.getType().equals(ItemEnum.TYPE_PERMISSION.getCode()) ? authManager.getPermission(name) : authManager.getRole(name);
            if (item != null) {
                authManager.revoke(item, assignBody.getUserId());
            }
        }
        return new ResultEntity<>();
    }

    @PostMapping("admin/reset-pwd")
    @ResponseBody
    public ResultEntity<Object> resetPwd(ServletRequest request, @Validated ResetPasswordForm resetPasswordForm) {

        Admin admin = (Admin) request.getAttribute("admin");
        Md5Hash md5 = new Md5Hash(resetPasswordForm.getOldPassword(), admin.getSalt());
        if (!admin.getPassword().equals(md5.toString())) {
            return ResultEntity.error("老密码不正确");
        }

        AdminEntity adminEntity = adminService.findOne(admin.getId());
        adminEntity.generatePassword(resetPasswordForm.getNewPassword());
        adminService.updateById(adminEntity);
        return ResultEntity.success();
    }




}
